<template>
  <div 
    class="parallax-container"
    ref="container"
    :style="containerStyles"
  >
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'ParallaxEffect',
  props: {
    depth: {
      type: Number,
      default: 30 // 视差效果深度
    },
    perspective: {
      type: Number,
      default: 1000 // 透视效果强度
    },
    easing: {
      type: Number,
      default: 0.05 // 平滑过渡系数
    },
    scale: {
      type: Number,
      default: 1.05 // 悬停时的缩放比例
    },
    shadow: {
      type: Boolean,
      default: true // 是否启用浮动阴影
    },
    glare: {
      type: Boolean,
      default: true // 是否启用反光效果
    },
    gyroscope: {
      type: Boolean,
      default: true // 陀螺仪支持(移动设备)
    }
  },
  data() {
    return {
      mouse: {
        x: 0,
        y: 0
      },
      rect: null,
      width: 0,
      height: 0,
      left: 0,
      top: 0,
      isActive: false,
      glareAngle: 0,
      glareOpacity: 0,
      transitionTimeout: null,
      gyroEnabled: false,
      gyroLastTimestamp: 0,
      rotateX: 0,
      rotateY: 0
    }
  },
  computed: {
    containerStyles() {
      return {
        perspective: `${this.perspective}px`,
        transform: this.isActive 
          ? `
            rotateX(${this.rotateX}deg) 
            rotateY(${this.rotateY}deg)
            scale3d(${this.scale}, ${this.scale}, ${this.scale})
          `
          : '',
        boxShadow: this.shadow && this.isActive 
          ? `0 ${Math.abs(this.rotateX) * 0.5}px ${Math.abs(this.rotateX) + Math.abs(this.rotateY)}px rgba(0,0,0,0.1)` 
          : '',
        transition: this.isActive ? 'none' : 'all 0.6s ease'
      }
    }
  },
  mounted() {
    this.initContainer();
    this.initEventListeners();
    
    // 检测设备是否支持陀螺仪
    if (this.gyroscope && window.DeviceOrientationEvent) {
      this.gyroEnabled = true;
    }
  },
  beforeUnmount() {
    this.cleanup();
  },
  methods: {
    initContainer() {
      const element = this.$refs.container;
      if (!element) return;
      
      this.updateElementPosition();
      
      // 添加反光效果元素
      if (this.glare) {
        const glareElement = document.createElement('div');
        glareElement.className = 'parallax-glare';
        
        const glareInner = document.createElement('div');
        glareInner.className = 'parallax-glare-inner';
        
        glareElement.appendChild(glareInner);
        element.appendChild(glareElement);
        
        // 基本样式
        Object.assign(glareElement.style, {
          position: 'absolute',
          top: '0',
          left: '0',
          width: '100%',
          height: '100%',
          overflow: 'hidden',
          borderRadius: 'inherit',
          pointerEvents: 'none',
          zIndex: '10'
        });
        
        Object.assign(glareInner.style, {
          position: 'absolute',
          top: '50%',
          left: '50%',
          width: '200%',
          height: '200%',
          transform: 'rotate(0deg) translate(-50%, -50%)',
          transformOrigin: '0% 0%',
          background: 'linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(255,255,255,0.8) 100%)',
          opacity: '0',
          pointerEvents: 'none'
        });
      }
    },
    
    initEventListeners() {
      window.addEventListener('resize', this.updateElementPosition);
      
      const element = this.$refs.container;
      if (element) {
        element.addEventListener('mouseenter', this.handleMouseEnter);
        element.addEventListener('mousemove', this.handleMouseMove);
        element.addEventListener('mouseleave', this.handleMouseLeave);
      }
      
      // 添加陀螺仪事件监听
      if (this.gyroEnabled) {
        window.addEventListener('deviceorientation', this.handleGyroscope);
      }
    },
    
    cleanup() {
      window.removeEventListener('resize', this.updateElementPosition);
      
      const element = this.$refs.container;
      if (element) {
        element.removeEventListener('mouseenter', this.handleMouseEnter);
        element.removeEventListener('mousemove', this.handleMouseMove);
        element.removeEventListener('mouseleave', this.handleMouseLeave);
      }
      
      if (this.gyroEnabled) {
        window.removeEventListener('deviceorientation', this.handleGyroscope);
      }
      
      clearTimeout(this.transitionTimeout);
    },
    
    updateElementPosition() {
      const element = this.$refs.container;
      if (!element) return;
      
      this.rect = element.getBoundingClientRect();
      this.width = element.offsetWidth;
      this.height = element.offsetHeight;
      this.left = this.rect.left;
      this.top = this.rect.top;
    },
    
    handleMouseEnter() {
      this.isActive = true;
      // 取消任何过渡动画
      clearTimeout(this.transitionTimeout);
    },
    
    handleMouseMove(e) {
      if (!this.isActive) return;
      
      // 获取相对于元素的鼠标位置
      const mouseX = e.clientX - this.left;
      const mouseY = e.clientY - this.top;
      
      // 计算旋转角度 - 从元素中心点计算
      const ratioX = (mouseX - this.width / 2) / (this.width / 2);
      const ratioY = (mouseY - this.height / 2) / (this.height / 2);
      
      const newRotateX = -ratioY * this.depth / 2;
      const newRotateY = ratioX * this.depth / 2;
      
      // 平滑过渡
      this.rotateX += (newRotateX - this.rotateX) * this.easing;
      this.rotateY += (newRotateY - this.rotateY) * this.easing;
      
      // 更新反光效果
      if (this.glare) {
        // 计算反光角度和亮度
        const angle = Math.atan2(mouseY - this.height / 2, mouseX - this.width / 2) * 180 / Math.PI;
        const distance = Math.sqrt(
          Math.pow(mouseX - this.width / 2, 2) + 
          Math.pow(mouseY - this.height / 2, 2)
        );
        
        const intensity = Math.min(distance / Math.sqrt(Math.pow(this.width / 2, 2) + Math.pow(this.height / 2, 2)), 1);
        
        this.glareAngle = angle;
        this.glareOpacity = intensity * 0.3; // 最大透明度30%
        
        // 更新反光样式
        const glareInner = this.$refs.container.querySelector('.parallax-glare-inner');
        if (glareInner) {
          glareInner.style.transform = `rotate(${this.glareAngle}deg) translate(-50%, -50%)`;
          glareInner.style.opacity = this.glareOpacity.toString();
        }
      }
    },
    
    handleMouseLeave() {
      // 缓慢恢复原状
      this.transitionTimeout = setTimeout(() => {
        this.isActive = false;
        this.rotateX = 0;
        this.rotateY = 0;
        
        // 恢复反光效果
        if (this.glare) {
          const glareInner = this.$refs.container.querySelector('.parallax-glare-inner');
          if (glareInner) {
            glareInner.style.opacity = '0';
          }
        }
      }, 100);
    },
    
    handleGyroscope(e) {
      if (!this.gyroEnabled || !this.isActive) return;
      
      // 防止过于频繁更新
      const now = performance.now();
      if (now - this.gyroLastTimestamp < 16) { // 约60fps
        return;
      }
      this.gyroLastTimestamp = now;
      
      // 获取设备方向
      const beta = e.beta; // 前后倾斜 -180 到 180
      const gamma = e.gamma; // 左右倾斜 -90 到 90
      
      // 限制倾斜角度
      const maxAngle = 15;
      const x = Math.max(Math.min(gamma, maxAngle), -maxAngle) / maxAngle;
      const y = Math.max(Math.min(beta, maxAngle), -maxAngle) / maxAngle;
      
      // 计算旋转角度
      const newRotateX = -y * this.depth / 3;
      const newRotateY = x * this.depth / 3;
      
      // 平滑过渡
      this.rotateX += (newRotateX - this.rotateX) * this.easing;
      this.rotateY += (newRotateY - this.rotateY) * this.easing;
      
      // 更新反光效果
      if (this.glare) {
        const angle = Math.atan2(y, x) * 180 / Math.PI;
        const intensity = Math.sqrt(x * x + y * y);
        
        this.glareAngle = angle;
        this.glareOpacity = intensity * 0.3;
        
        // 更新反光样式
        const glareInner = this.$refs.container.querySelector('.parallax-glare-inner');
        if (glareInner) {
          glareInner.style.transform = `rotate(${this.glareAngle}deg) translate(-50%, -50%)`;
          glareInner.style.opacity = this.glareOpacity.toString();
        }
      }
    }
  }
}
</script>

<style scoped>
.parallax-container {
  position: relative;
  transform-style: preserve-3d;
  will-change: transform;
  transition: all 0.5s ease;
  box-shadow: 0 10px 30px rgba(0,0,0,0.05);
  border-radius: inherit;
}
</style> 